package com.company.project.service.impl;

import java.util.Date;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.company.project.constant.TradeEnums;
import com.company.project.core.AbstractService;
import com.company.project.dao.TradeGoodsMapper;
import com.company.project.dao.TradeGoodsNumberLogMapper;
import com.company.project.dao.TradeMqConsumerLogMapper;
import com.company.project.model.TradeGoods;
import com.company.project.model.TradeGoodsNumberLog;
import com.company.project.protocol.goods.AddGoodsNumberReq;
import com.company.project.protocol.goods.AddGoodsNumberRes;
import com.company.project.protocol.goods.QueryGoodsReq;
import com.company.project.protocol.goods.QueryGoodsRes;
import com.company.project.protocol.goods.ReduceGoodsNumberReq;
import com.company.project.protocol.goods.ReduceGoodsNumberRes;
import com.company.project.service.TradeGoodsService;

/**
 * Created by CodeGenerator on 2018/12/07.
 */
@Service
@Transactional
public class TradeGoodsServiceImpl extends AbstractService<TradeGoods> implements TradeGoodsService {
	private static final Logger LOGGER = LoggerFactory.getLogger(TradeGoodsServiceImpl.class);
	@Resource
	private TradeGoodsMapper tradeGoodsMapper;

	@Resource
	private TradeGoodsNumberLogMapper tradeGoodsNumberLogMapper;

	/* 消费日志表（trade-mq-consumer-log） */
	@Resource
	private TradeMqConsumerLogMapper tradeMqConsumerLogMapper;

	public QueryGoodsRes queryGoods(QueryGoodsReq queryGoodsReq) {
		QueryGoodsRes queryGoodsRes = new QueryGoodsRes();
		queryGoodsRes.setRetCode(TradeEnums.RetEnum.SUCCESS.getCode());
		queryGoodsRes.setRetInfo(TradeEnums.RetEnum.SUCCESS.getDesc());
		try {
			if (queryGoodsReq == null || queryGoodsReq.getGoodsId() == null) {
				throw new Exception("查询商品信息ID不正确");
			}
			TradeGoods tradeGoods = this.tradeGoodsMapper.selectByPrimaryKey(queryGoodsReq.getGoodsId());
			if (tradeGoods != null) {
				BeanUtils.copyProperties(tradeGoods, queryGoodsRes);
			} else {
				throw new Exception("未查询到商品");
			}
		} catch (Exception ex) {
			queryGoodsRes.setRetCode(TradeEnums.RetEnum.FAIL.getCode());
			queryGoodsRes.setRetInfo(ex.getMessage());
		}
		return queryGoodsRes;
	}

	// @Transactional
	public ReduceGoodsNumberRes reduceGoodsNumber(ReduceGoodsNumberReq reduceGoodsNumberReq) {
		ReduceGoodsNumberRes reduceGoodsNumberRes = new ReduceGoodsNumberRes();
		reduceGoodsNumberRes.setRetCode(TradeEnums.RetEnum.SUCCESS.getCode());
		reduceGoodsNumberRes.setRetInfo(TradeEnums.RetEnum.SUCCESS.getDesc());
		if (reduceGoodsNumberReq == null || reduceGoodsNumberReq.getGoodsId() == null
				|| reduceGoodsNumberReq.getGoodsNumber() == null || reduceGoodsNumberReq.getGoodsNumber() <= 0) {

			throw new RuntimeException("扣减库存请求参数不正确");
		}
		TradeGoods tradeGoods = new TradeGoods();
		tradeGoods.setGoodsId(reduceGoodsNumberReq.getGoodsId());
		tradeGoods.setGoodsNumber(reduceGoodsNumberReq.getGoodsNumber());
		int record = this.tradeGoodsMapper.reduceGoodsNumber(tradeGoods);
		if (record <= 0) {
			throw new RuntimeException("扣减库存失败");
		}
		TradeGoodsNumberLog tradeGoodsNumberLog = new TradeGoodsNumberLog();
		tradeGoodsNumberLog.setGoodsId(reduceGoodsNumberReq.getGoodsId());
		tradeGoodsNumberLog.setGoodsNumber(reduceGoodsNumberReq.getGoodsNumber());
		tradeGoodsNumberLog.setOrderId(reduceGoodsNumberReq.getOrderId());
		tradeGoodsNumberLog.setLogTime(new Date());
		this.tradeGoodsNumberLogMapper.insert(tradeGoodsNumberLog);
		return reduceGoodsNumberRes;

	}

	public AddGoodsNumberRes addGoodsNumber(AddGoodsNumberReq addGoodsNumberReq) {
		AddGoodsNumberRes addGoodsNumberRes = new AddGoodsNumberRes();
		addGoodsNumberRes.setRetCode(TradeEnums.RetEnum.SUCCESS.getCode());
		addGoodsNumberRes.setRetInfo(TradeEnums.RetEnum.SUCCESS.getDesc());
		if (addGoodsNumberReq == null || addGoodsNumberReq.getGoodsId() == null
				|| addGoodsNumberReq.getGoodsNumber() == null || addGoodsNumberReq.getGoodsNumber() <= 0) {

			throw new RuntimeException("增加库存请求参数不正确");
		}
		if (addGoodsNumberReq.getOrderId() != null) {
			// TradeGoodsNumberLogKey key=new TradeGoodsNumberLogKey();
			// key.setGoodsId(addGoodsNumberReq.getGoodsId());
			// key.setOrderId(addGoodsNumberReq.getOrderId());
			// TradeGoodsNumberLog
			// tradeGoodsNumberLog=this.tradeGoodsNumberLogMapper.selectByPrimaryKey(key);
			// 联合主键查找
			// TODO
			TradeGoodsNumberLog tradeGoodsNumberLog = this.tradeGoodsNumberLogMapper.selectByOrderidAndGoodsId(
					addGoodsNumberReq.getGoodsId(), addGoodsNumberReq.getOrderId());
			if (tradeGoodsNumberLog == null) {
				throw new RuntimeException("未找到扣库存记录");
			}
		}
		TradeGoods tradeGoods = new TradeGoods();
		tradeGoods.setGoodsId(addGoodsNumberReq.getGoodsId());
		tradeGoods.setGoodsNumber(addGoodsNumberReq.getGoodsNumber());
		int record = this.tradeGoodsMapper.addGoodsNumber(tradeGoods);
		if (record <= 0) {
			throw new RuntimeException("扣减库存失败");
		}
		return addGoodsNumberRes;
	}

	/*
	 * // 消息处理 （加库存）必须幂等处理 // 用压测 进行并发测试 public boolean addGoodsNumberMsg(String
	 * groupName,String keys,String tags,String body,String msgId) {
	 * 
	 * // 从MQ，消费日志表 用联合主键groupName,msgKey以及tag 查找 TradeMqConsumerLog
	 * queryConsumerLog = new TradeMqConsumerLog();
	 * queryConsumerLog.setMsgKeys(keys);
	 * queryConsumerLog.setGroupName(groupName);
	 * queryConsumerLog.setMsgTag(tags); TradeMqConsumerLog mqConsumerLog =
	 * this.tradeMqConsumerLogMapper.selectOne(queryConsumerLog);
	 * 
	 * if (mqConsumerLog != null) {//日志消息表里面已经有值 try { String consumerStatus =
	 * mqConsumerLog.getConsumerStatus(); // 消息已经处理过了 if
	 * (MQEnums.ConsumerStatusEnum
	 * .SUCCESS.getStatusCode().equals(consumerStatus)) {
	 * LOGGER.warn("已经处理过了，不能再处理了"); return true; } else if
	 * (MQEnums.ConsumerStatusEnum
	 * .PROCESSING.getStatusCode().equals(consumerStatus)) {
	 * LOGGER.warn("正在处理稍后再试"); return false; } else if
	 * (MQEnums.ConsumerStatusEnum.FAIL.getStatusCode().equals(consumerStatus))
	 * { if (mqConsumerLog.getConsumerTimes() >= 3) { // 让这个消息不再重试，转人工处理
	 * LOGGER.warn("超过三次，不再处理"); return true; } TradeMqConsumerLog
	 * updateMqConsumerLog = new TradeMqConsumerLog();
	 * updateMqConsumerLog.setGroupName(groupName);
	 * updateMqConsumerLog.setMsgKeys(keys);
	 * updateMqConsumerLog.setMsgTag(tags);
	 * updateMqConsumerLog.setConsumerStatus
	 * (MQEnums.ConsumerStatusEnum.PROCESSING.getStatusCode());
	 * 
	 * // 乐观锁的方式防止并发更新，只有一个处理者能成功 // int record =
	 * this.tradeMqConsumerLogMapper.updateByConditionSelective
	 * (updateMqConsumerLog, // tradeMqConsumerLogExample);
	 * 
	 * // TradeMqConsumerLogExample tradeMqConsumerLogExample = new
	 * TradeMqConsumerLogExample(); //
	 * tradeMqConsumerLogExample.createCriteria() //
	 * .andGroupNameEqualTo(mqConsumerLog.getGroupName()) //
	 * .andMsgKeyEqualTo(mqConsumerLog.getMsgKey()) //
	 * .andMsgTagEqualTo(mqConsumerLog.getMsgTag()) //
	 * .andConsumerTimesEqualTo(mqConsumerLog.getConsumerTimes());//这个条件是重点 //
	 * 乐观锁的方式防止并发更新，只有一个处理者能成功 // int record =
	 * this.tradeMqConsumerLogMapper.updateByExampleSelective
	 * (updateMqConsumerLog, // tradeMqConsumerLogExample); // TODO // int
	 * record=0; // if (record <= 0) { // LOGGER.warn("并发更新处理状态，一会儿重试"); //
	 * return false; // }
	 * 
	 * //业务逻辑处理 CancelOrderMQ cancelOrderMQ = JSON.parseObject(body,
	 * CancelOrderMQ.class); AddGoodsNumberReq addGoodsNumberReq = new
	 * AddGoodsNumberReq();
	 * addGoodsNumberReq.setGoodsId(cancelOrderMQ.getGoodsId());
	 * addGoodsNumberReq.setGoodsNumber(cancelOrderMQ.getGoodsNumber());
	 * addGoodsNumberReq.setOrderId(cancelOrderMQ.getOrderId());
	 * this.addGoodsNumber(addGoodsNumberReq);
	 * 
	 * // 更新消息处理成功 TradeMqConsumerLog updateMqConsumerLog = new
	 * TradeMqConsumerLog(); updateMqConsumerLog.setGroupName(groupName);
	 * updateMqConsumerLog.setMsgKeys(keys);
	 * updateMqConsumerLog.setMsgTag(tags);
	 * updateMqConsumerLog.setConsumerTimes(1);
	 * updateMqConsumerLog.setMsgId(msgId);
	 * updateMqConsumerLog.setMsgBody(body);
	 * updateMqConsumerLog.setConsumerStatus
	 * (MQEnums.ConsumerStatusEnum.SUCCESS.getStatusCode());
	 * this.tradeMqConsumerLogMapper
	 * .updateByPrimaryKeySelective(updateMqConsumerLog); return true;
	 * 
	 * } return true; } catch (Exception e) { TradeMqConsumerLog
	 * updateMqConsumerLog = new TradeMqConsumerLog();
	 * updateMqConsumerLog.setGroupName(queryConsumerLog.getGroupName());
	 * updateMqConsumerLog.setMsgKeys(queryConsumerLog.getMsgKeys());
	 * updateMqConsumerLog.setMsgTag(queryConsumerLog.getMsgTag());
	 * updateMqConsumerLog.setConsumerTimes(mqConsumerLog.getConsumerTimes() +
	 * 1);
	 * updateMqConsumerLog.setConsumerStatus(MQEnums.ConsumerStatusEnum.FAIL.
	 * getStatusCode());
	 * this.tradeMqConsumerLogMapper.updateByPrimaryKeySelective
	 * (updateMqConsumerLog); return false; } } else { //日志消息表里面没值 //
	 * 新插入去重表，并发时用主键冲突控制 try { TradeMqConsumerLog tradeMqConsumerLog = new
	 * TradeMqConsumerLog(); tradeMqConsumerLog.setGroupName(groupName);
	 * tradeMqConsumerLog.setMsgKeys(keys); tradeMqConsumerLog.setMsgTag(tags);
	 * tradeMqConsumerLog.setConsumerTimes(0);
	 * tradeMqConsumerLog.setMsgId(msgId); tradeMqConsumerLog.setMsgBody(body);
	 * tradeMqConsumerLog
	 * .setConsumerStatus(MQEnums.ConsumerStatusEnum.PROCESSING
	 * .getStatusCode());
	 * this.tradeMqConsumerLogMapper.insertSelective(tradeMqConsumerLog);
	 * 
	 * //业务逻辑处理 CancelOrderMQ cancelOrderMQ = JSON.parseObject(body,
	 * CancelOrderMQ.class); AddGoodsNumberReq addGoodsNumberReq = new
	 * AddGoodsNumberReq();
	 * addGoodsNumberReq.setGoodsId(cancelOrderMQ.getGoodsId());
	 * addGoodsNumberReq.setGoodsNumber(cancelOrderMQ.getGoodsNumber());
	 * addGoodsNumberReq.setOrderId(cancelOrderMQ.getOrderId());
	 * this.addGoodsNumber(addGoodsNumberReq);
	 * 
	 * // 更新消息处理成功 TradeMqConsumerLog updateMqConsumerLog = new
	 * TradeMqConsumerLog(); updateMqConsumerLog.setGroupName(groupName);
	 * updateMqConsumerLog.setMsgKeys(keys);
	 * updateMqConsumerLog.setMsgTag(tags);
	 * updateMqConsumerLog.setConsumerTimes(1);
	 * updateMqConsumerLog.setMsgId(msgId);
	 * updateMqConsumerLog.setMsgBody(body);
	 * updateMqConsumerLog.setConsumerStatus
	 * (MQEnums.ConsumerStatusEnum.SUCCESS.getStatusCode());
	 * this.tradeMqConsumerLogMapper
	 * .updateByPrimaryKeySelective(updateMqConsumerLog); return true;
	 * 
	 * } catch (Exception e) { LOGGER.warn("主键冲突，说明有订阅者正在处理，稍后再试");
	 * TradeMqConsumerLog updateMqConsumerLog = new TradeMqConsumerLog();
	 * updateMqConsumerLog.setGroupName(queryConsumerLog.getGroupName());
	 * updateMqConsumerLog.setMsgKeys(queryConsumerLog.getMsgKeys());
	 * updateMqConsumerLog.setMsgTag(queryConsumerLog.getMsgTag());
	 * updateMqConsumerLog.setConsumerTimes(0);
	 * updateMqConsumerLog.setConsumerStatus
	 * (MQEnums.ConsumerStatusEnum.FAIL.getStatusCode());
	 * this.tradeMqConsumerLogMapper
	 * .updateByPrimaryKeySelective(updateMqConsumerLog); return false; } } }
	 */
}
